﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CreditCalc_v02
{
    class Program
    {
        static void Main()
        {
            Console.BackgroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Black;
            Console.SetCursorPosition(30,0); Console.WriteLine(" КРЕДИТНЫЙ КАЛЬКУЛЯТОР ");
            Console.ResetColor(); Console.SetCursorPosition(5, 2);
            Console.ForegroundColor = ConsoleColor.DarkGray;
            Console.Write("Данная программа сформирует календарь платежей по заданным вами параметрам КРЕДИТА. Размер ежемесячного платежа равен сумме платежей по телу кредита и комиссии банка. Комиссия банка начисляется ежемесячно классическим способом на остаток от тела кредита в размере согласно годовой процентной ставки. Платежи, которые приходятся на выходные дни, переносятся на ближайшую пятницу, им предшествующую.");
            Console.WriteLine(" После ввода каждого из параметров нажимайте Enter.");
            Console.WriteLine("");
            Console.ForegroundColor = ConsoleColor.Gray; Console.Write("Сумма кредита, грн.: ");
            decimal amount = (decimal)ReadUintFromConsole();
            Console.ForegroundColor = ConsoleColor.Gray; Console.Write("Годовой процент, %: ");
            decimal interestRate = (decimal)ReadUintFromConsole();
            Console.ForegroundColor = ConsoleColor.Gray; Console.Write("Дата получения кредита: ");
            DateTime startDate = ReadDateFromConsole();
            Console.ForegroundColor = ConsoleColor.Gray; Console.Write("Количество ежемесячных платежей: ");
            int numPayments = (int)ReadPosIntFromConsole();            
            Payment[] schedule = GenerateSchedule(amount, startDate, interestRate, numPayments);
            decimal[] creditResume=GenerateCreditResume(schedule);
            Console.ResetColor();
            PrintCreditResume (creditResume);            
            PrintArray(schedule);
            Console.ReadKey();
        }
        static uint ReadUintFromConsole()
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                return (uint.Parse(Console.ReadLine()));                
            }
            catch
            {
                Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Ошибка ввода, повторите");
                Console.ResetColor();
                return ReadUintFromConsole();
            }            
        }
        static uint ReadPosIntFromConsole()
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                uint a = uint.Parse(Console.ReadLine());
                if (a > 0)
                {
                    return (a);
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Ошибка ввода, повторите");
                    Console.ResetColor();
                    return ReadPosIntFromConsole();
                }
            }
            catch
            {
                Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Ошибка ввода, повторите");
                Console.ResetColor();
                return ReadPosIntFromConsole();
            }            
        }
        static DateTime ReadDateFromConsole()
        {
            DateTime dt;
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            string s=Console.ReadLine();
            if(DateTime.TryParse(s, out dt))
            {
                return dt;
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Ошибка ввода, повторите");
                Console.ResetColor();
                return ReadDateFromConsole();
            }
        }
        static Payment[] GenerateSchedule(decimal amount, DateTime startDate, decimal interestRate, int numPayments)
        {
            Payment[] array = new Payment [numPayments];           
            Decimal checkamount = amount;  
            DateTime checkdate = startDate.AddMonths(1);
            int count = 0;
            while (count < numPayments)
            {
                Payment p = new Payment();
                p.Number = count+1;
                p.DueDate = checkdate;
                if (checkdate.DayOfWeek == DayOfWeek.Saturday)
                {
                    p.DueDate = checkdate.AddDays(-1);
                }
                else if (checkdate.DayOfWeek == DayOfWeek.Sunday)
                {
                    p.DueDate = checkdate.AddDays(-2);
                }
                p.PrincipalAmount = amount / numPayments;
                if (count == numPayments - 1)
                {
                    p.PrincipalAmount = checkamount;
                }
                var span = checkdate.Subtract(checkdate.AddMonths(-1));
                int days = span.Days;                
                p.InterestAmount = checkamount * interestRate * days / 100 / 365;  
                array[count] = p;
                checkamount = checkamount - p.PrincipalAmount;
                checkdate = checkdate.AddMonths(1);
                count++;
            }
            return array; 
        }
        static decimal[] GenerateCreditResume(Payment[] array)
        {
            decimal interestAmount = 0;
            decimal principalAmount = 0;
            for (int i = 0; i < array.Length; i++)
            {
                Payment p = array[i];
                interestAmount = interestAmount + p.InterestAmount;
                principalAmount = principalAmount + p.PrincipalAmount;
            }
            decimal wholePayment = interestAmount + principalAmount;
            Payment Last = array[array.Length - 1];
            int yearsround = Last.Number / 12;
            decimal years = (decimal)yearsround;
            decimal months = (decimal) Last.Number - years * 12;
            decimal[] creditResume = new decimal[5] { years, months, wholePayment, principalAmount, interestAmount };
            return creditResume;
        }
        static void PrintArray(Payment[] array)
        {
            //for (int n = 0; n < Console.WindowWidth; n++) { Console.Write("="); }
            Console.WriteLine(""); Console.WriteLine("                                 ПЛАТЕЖНЫЙ КАЛЕНДАРЬ");
            for (int n = 0; n < Console.WindowWidth; n++) { Console.Write("-"); }
            for (int i = 0; i < array.Length; i++)
            {
                Payment p = array[i];
                decimal payment = p.PrincipalAmount + p.InterestAmount;
                Console.Write("Платеж {0}: ", p.Number.ToString("000"));
                Console.Write(" {0}  {1}", p.DueDate.ToString("yyyy.MM.dd"), p.DueDate.ToString("ddd"));
                Console.WriteLine("  Сумма платежа: {0} грн.", payment.ToString("0.00"));
            }
            for (int n = 0; n < Console.WindowWidth; n++) { Console.Write("-"); }
        }
        static void PrintCreditResume(decimal[] array)
        {
            Console.WriteLine("");
            Console.WriteLine("                                   РАСЧЕТ КРЕДИТА");
            for (int n = 0; n < Console.WindowWidth; n++) { Console.Write("-"); }            
            Console.WriteLine("Рачетный срок погашения кредита через");
            Console.WriteLine("   годов:   {0}", array[0].ToString("0"));
            Console.WriteLine("   месяцев: {0}", array[1].ToString("0"));
            Console.WriteLine("");
            Console.WriteLine("Сумма всех платежей: {0} грн.", array[2].ToString("0.00"));
            Console.WriteLine("В том числе,");
            Console.WriteLine("       тело кредита: {0} грн.", array[3].ToString("0.00"));
            Console.WriteLine("     комиссия банка: {0} грн.", array[4].ToString("0.00")); 
        }
    }
}
